#!/usr/bin/python3
# -*- coding: UTF-8 -*-

import tkinter as tk
import threading
import time
import socketserver
import json


font_size = 8

stuff_width = 5
stuff_hight = 3

location_width = 6
location_hight = 2


location_num = 40
passage_num  = 4
location_per_passage = 48


class stuff(object):
    """docstring for stuff"""
    def __init__(self, window, area, index, column, passage):
        super(stuff, self).__init__()
        self.window = window
        self.area = area
        self.index = index
        self.column = column
        self.passage = passage

        # if (self.passage & 1) == 0:
        #     s_row = self.passage * 2
        #     l_row = self.passage * 2 + 1
        # else:
        #     s_row = self.passage * 2 + 1
        #     l_row = self.passage * 2

        s_row = self.passage * 2
        l_row = self.passage * 2 + 1

        self.label_s = tk.Label(self.window, text = "",
                                            bg = 'red',
                                            width = stuff_width,
                                            height = stuff_hight,
                                            font = ('Arial', font_size),)
        self.label_s.grid(row = s_row, column = self.column, sticky = tk.N + tk.S)

        self.label_l = tk.Label(self.window, text = "%c-%03d" % (area, index),
                                            width = location_width,
                                            height = location_hight,
                                            font = ('Arial', font_size),)
        self.label_l.grid(row = l_row, column = self.column, sticky = tk.N)

    def set_online(self, name):
        self.label_s.configure(bg = 'green')
        if name:
            self.label_s.config(text = name)

    def set_offline(self):
        self.label_s.configure(bg = 'red')
        self.label_s.config(text = "")

    def info_dump(self):
        print("area %s index %d column %d passage %d" % (self.area, self.index, self.column, self.passage))


class QRCodeRecv(socketserver.BaseRequestHandler):
    def handle(self):
        try:
            while True:
                self.data = self.request.recv(1024)
                # print("{} send:".format(self.client_address), self.data)
                if not self.data:
                    print("connection lost")
                    break
                    
                parse_cli_info(bytes.decode(self.data))
                # self.request.sendall(self.data.upper())
        except Exception as e:
            print(self.client_address, "disconnect")
        finally:
            self.request.close()

    def setup(self):
        print("before handle, connect with", self.client_address)

    def finish(self):
        print("finish run after handle")


class ServiceThread(threading.Thread):
    """docstring for ServiceThread"""
    def __init__(self):
        super(ServiceThread, self).__init__()
    
    def run(self):
        print("start tcp server")

        addr = ("localhost", 8080)
        self.svr = socketserver.TCPServer(addr, QRCodeRecv)
        self.svr.serve_forever()
        print("serve_forever shutdown")

    def stop_svr(self):
        print("stop tcp server")
        self.svr.shutdown()


def parse_cli_info(data):
    # print(data)
    info_dict = json.loads(data)
    # print(info_dict)

    if 'area' in info_dict and 'num' in info_dict and 'dir' in info_dict:
        area = ord(info_dict['area']) - ord('A')
        index = info_dict['num'] - 1
        direct = info_dict['dir']

        if 'prod' in info_dict:
            name = info_dict['prod']
        else:
            name = None

        print("area %d index %d direct %d name %s" % (area, index, direct, name))

        if direct:
            stuff_passage[area][index].set_online(name)
            print("(TODO: here could use audio nitofy)")
        else:
            if not name:
                stuff_passage[area][index].set_offline()
                print("(TODO: here could use audio nitofy)")
            else:
                print("scan error!!! (TODO: here could use audio alarm)")
    else:
        print("not contain 'area' or 'num' or 'dir'")


try:
    window = tk.Tk()
    window.title('仓库存货 - 看板')

    # window.attributes("-fullscreen", True)
    
    w = window.winfo_screenwidth()
    h = window.winfo_screenheight()
    window.geometry("%dx%d" % (w, h))

    passage = 0
    stuff_passage = []
    for j in range(0, passage_num):
        stuff_location = []
        stuff_passage.append(stuff_location)

        column = 0
        for i in range(0, location_num):
            if i != 0 and i % location_per_passage == 0:
                passage += 1
                column = 0

            stuff_location.append(stuff(window, chr(ord('A') + j), i + 1, column, passage))
            column += 1

        # new passage
        passage += 1

    service = ServiceThread()
    service.start()
    print("server thread running...")

    window.mainloop()

    service.stop_svr()
    service.join()


except Exception as e:
    raise e

finally:
    pass
